package space.misiro.ledgers.keycloak.client.rest

import feign.Headers
import org.keycloak.representations.AccessToken
import org.keycloak.representations.AccessTokenResponse
import org.springframework.cloud.openfeign.FeignClient
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestHeader
import space.misiro.ledgers.keycloak.client.model.TokenConfiguration

/**
 * Keycloak Token 管理接口客户端
 *
 * @property url 从配置文件中注入的Keycloak认证服务器地址（keycloak.auth-server-url）
 * @FeignClient 使用配置名称 keycloakTokenRestClient
 * @Headers 默认请求头设置为表单编码格式
 */
@FeignClient(value = "keycloakTokenRestClient", url = "\${keycloak.auth-server-url}")
@Headers("Content-Type: application/x-www-form-urlencoded")
interface KeycloakTokenRestClient {

    /**
     * 执行标准OAuth2密码模式登录认证
     *
     * @param formParams 包含认证参数的表单数据（如grant_type, username, password等）
     * @return 包含访问令牌的响应实体，响应体为包含access_token, expires_in等字段的键值对
     * @PostMapping 请求路径包含动态realm配置，consumes指定为表单编码格式
     */
    @SuppressWarnings("java:51452")
    @PostMapping(
        value = ["/realms/\${keycloak.realm}/protocol/openid-connect/token"],
        consumes = [MediaType.APPLICATION_FORM_URLENCODED_VALUE]
    )
    fun login(@RequestBody formParams: Map<String, *>): ResponseEntity<Map<String, *>>

    /**
     * 交换/更新访问令牌
     *
     * @param token 授权头中的Bearer令牌
     * @param tokenConfiguration 令牌配置参数（如有效期、作用域等）
     * @return 包含新访问令牌的响应实体
     * @PostMapping 请求路径包含动态realm配置
     */
    @PostMapping(value = ["/realms/\${keycloak.realm}/configurable-token"])
    fun exchangeToken(
        @RequestHeader("Authorization") token: String,
        @RequestBody tokenConfiguration: TokenConfiguration
    ): ResponseEntity<AccessTokenResponse>

    /**
     * 验证访问令牌有效性
     *
     * @param formParams 包含令牌验证参数的表单数据（通常包含token参数）
     * @return 包含令牌详细信息的响应实体
     * @PostMapping 请求路径指向令牌验证端点，consumes指定为表单编码格式
     */
    @PostMapping(
        value = ["/realms/\${keycloak.realm}/protocol/openid-connect/token/introspect"],
        consumes = [MediaType.APPLICATION_FORM_URLENCODED_VALUE]
    )
    fun validate(formParams: Map<String, *>): ResponseEntity<AccessToken>

    /**
     * 触发用户执行邮件验证操作
     *
     * @param bearerToken 管理员授权头中的Bearer令牌
     * @param userId 需要验证的目标用户ID
     * @param requiredActions 需要用户执行的验证操作列表
     * @return 操作结果响应实体（可能包含令牌信息）
     * @PostMapping 请求路径包含动态realm配置和用户ID路径参数
     */
    @PostMapping(value = ["/admin/realms/\${keycloak.realm}/users/{user-id}/execute-actions-email"])
    fun executeActionsEmail(
        @RequestHeader("Authorization") bearerToken: String,
        @PathVariable("user-id") userId: String,
        @RequestBody requiredActions: List<String>
    ): ResponseEntity<AccessTokenResponse>
}
